package com.ucode.hrm.service.impl;

import com.ucode.hrm.mapper.HrmSocialSecurityHistoricalRuleMapper;
import com.ucode.hrm.mapper.HrmSocialSecurityRuleMapper;
import com.ucode.hrm.service.HrmSocialSecurityRuleService;
import com.ucode.model.hrm.HrmSocialSecurityHistoricalRule;
import com.ucode.model.hrm.HrmSocialSecurityRule;
import com.ucode.model.hrm.HrmSocialSecurityRuleItem;
import com.ucode.model.hrm.enums.HrmSysResultCodeEnum;
import com.ucode.tool.exception.UcodeServiceException;
import com.ucode.tool.util.CollectionUtils;
import com.ucode.tool.util.IdentifyUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class HrmSocialSecurityRuleServiceImpl implements HrmSocialSecurityRuleService {

    @Resource
    private HrmSocialSecurityRuleMapper hrmSocialSecurityRuleMapper;
    @Resource
    private HrmSocialSecurityHistoricalRuleMapper hrmSocialSecurityHistoricalRuleMapper;

    @Override
    public HrmSocialSecurityRuleMapper initMapper() {
        return hrmSocialSecurityRuleMapper;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int update(HrmSocialSecurityRule hrmSocialSecurityRule) {
        /**
         * 更新社保规则
         * 1. 检查规则内容是否变更
         * 2. 如有变更，归档当前规则到历史表
         * 3. 更新新规则版本
         */
        HrmSocialSecurityRule dbBean = this.validate(hrmSocialSecurityRule.getId());

        if(hasRuleChanged(hrmSocialSecurityRule, dbBean)){

            HrmSocialSecurityHistoricalRule historicalRule = new HrmSocialSecurityHistoricalRule();
            historicalRule.setId(IdentifyUtils.getDefaultSnowflakeId());
            historicalRule.setRuleId(dbBean.getId());
            historicalRule.setItems(dbBean.getItems());
            historicalRule.setEffectiveDate(dbBean.getEffectiveDate());
            hrmSocialSecurityHistoricalRuleMapper.insert(historicalRule);
        }

        int i = hrmSocialSecurityRuleMapper.update(hrmSocialSecurityRule);
        if(i == 0){
            throw new UcodeServiceException(HrmSysResultCodeEnum.SOCIAL_SECURITY_RULE_NOT_EXISTS);
        }

        return i;
    }


    /**
     * 检查规则主体是否变更
     * @param current 当前数据库的规则
     * @param updated 更新后的规则
     * @return
     */
    private boolean hasRuleChanged(HrmSocialSecurityRule current, HrmSocialSecurityRule updated) {
        // 比较规则的关键字段
        if (!current.getEffectiveDate().equals(updated.getEffectiveDate())) return true;
        // 快速检查：数量不同则一定变更
        if (current.getItems().size() != updated.getItems().size()) {
            return true;
        }

        // 使用独立方法分离核心比较逻辑
        if (ruleItemSizeChanged(current.getItems(), updated.getItems())) return true;
        return ruleItemContentChanged(current.getItems(), updated.getItems());
    }

    /**
     * 快速检查数量变化
     */
    private boolean ruleItemSizeChanged(List<HrmSocialSecurityRuleItem> current,
                                         List<HrmSocialSecurityRuleItem> updated) {
        // 使用集合并集大小检查，避免多次.size()调用
        Set<Integer> currentTypes = current.stream()
                .map(HrmSocialSecurityRuleItem::getCoverageType)
                .collect(Collectors.toSet());
        Set<Integer> updatedTypes = updated.stream()
                .map(HrmSocialSecurityRuleItem::getCoverageType)
                .collect(Collectors.toSet());

        // 合并后大小应该等于单个集合大小（没有新增/删除）
        Set<Integer> union = new HashSet<>(currentTypes);
        union.addAll(updatedTypes);
        return union.size() != currentTypes.size();
    }

    /**
     * 详细比较覆盖内容变化
     */
    private boolean ruleItemContentChanged(List<HrmSocialSecurityRuleItem> currentList,
                                            List<HrmSocialSecurityRuleItem> updatedList) {
        // 创建类型->覆盖项的查找表（类型必须唯一）
        Map<Integer, HrmSocialSecurityRuleItem> currentMap = CollectionUtils.convertMap(currentList, HrmSocialSecurityRuleItem::getCoverageType);
        Map<Integer, HrmSocialSecurityRuleItem> updatedMap = CollectionUtils.convertMap(updatedList, HrmSocialSecurityRuleItem::getCoverageType);

        // 检查每个类型在两个版本中的差异
        for (Integer type : currentMap.keySet()) {
            HrmSocialSecurityRuleItem current = currentMap.get(type);
            HrmSocialSecurityRuleItem updated = updatedMap.get(type);

            // 类型存在于当前但不存在于更新
            if (updated == null) return true;

            // 详细字段比较
            if (isRuleItemFieldChanged(current, updated)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 比较单个覆盖项的各个字段变化
     */
    private boolean isRuleItemFieldChanged(HrmSocialSecurityRuleItem current, HrmSocialSecurityRuleItem updated) {
        return current.getBaseAmount().compareTo(updated.getBaseAmount()) != 0 ||
                current.getPersonalRate().compareTo(updated.getPersonalRate()) != 0 ||
                current.getCompanyRate().compareTo(updated.getCompanyRate()) != 0;
    }

}
